//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

/* Global compile-time options for elastos */
#ifdef WIN32
#undef WIN32
#endif

#ifdef _WIN32
#undef _WIN32
#endif

#ifdef _DEBUG
#ifndef DEBUG
#define DEBUG 1
#endif
#endif

#ifndef ELASTOS
#define ELASTOS 1
#endif
/* End global compile-time options for elastos */

#ifdef ELASTOS
#include <elastos.h>
#include <usyscall.h>
#include <memspy.h>
#include <elacfg.h>
#include <elacs.h>

#define FOOTERS 0
#define USE_DL_PREFIX 1
#define REALLOC_ZERO_BYTES_FREES 1
#define USE_LOCKS 1
#define MSPACES 1
#define HAVE_MMAP 1
#define HAVE_MORECORE 1
#define MORECORE_CONTIGUOUS 1
#define LACKS_UNISTD_H
#define LACKS_STDIO_H
#define LACKS_SYS_TYPES_H
#define LACKS_SYS_PARAM_H
#define LACKS_SYS_MMAN_H
#define LACKS_STRINGS_H
#define LACKS_SYS_TYPES_H
#define LACKS_FCNTL_H
#define MMAP_CLEARS 0
#define MALLOC_FAILURE_ACTION
#define ABORT assert(0)
#define DEFAULT_MMAP_THRESHOLD ((size_t)32U * (size_t)1024U)
#define DEFAULT_TRIM_THRESHOLD ((size_t)512U * (size_t)1024U)

#define malloc_getpagesize          ((size_t)4096U)
typedef int ptrdiff_t;
#endif

#include "malloc.c"

#ifdef ELASTOS

static void *sbrk(ptrdiff_t bytes)
{
    static unsigned int s_total_heap_bytes = 0;
    void *p = (void *)(unsigned int)-1;

    if (bytes) {
        ECode ec = SysBreak(USER_HEAP_BASE + s_total_heap_bytes + bytes);
        if (ec == NOERROR) {
            p = (void *)(char *)(USER_HEAP_BASE + s_total_heap_bytes);
            s_total_heap_bytes += bytes;
        }
//        else {
//            printf("HEAP: SysBreak() failed(0x%08X).\n", ec);
//        }
    } else {
        p = (void *)(char *)(USER_HEAP_BASE + s_total_heap_bytes);
    }

    return p;
}

void InitTaskMemory()
{
    INITIAL_LOCK(&magic_init_mutex);
    INITIAL_LOCK(&morecore_mutex);
    init_mparams();
}

void UninitTaskMemory()
{
    UNINITIAL_LOCK(&gm->mutex);
    UNINITIAL_LOCK(&morecore_mutex);
    UNINITIAL_LOCK(&magic_init_mutex);
}

#if defined(MEMORYSPY) //DEBUG, OPTIMIZE
void *TaskMemAlloc(UInt32 size, _ELASTOS Boolean zeroMem)
#else // RELEASE
ELAPI_(PVoid) _CMemoryHeap_Alloc(MemorySize size, Boolean zeroMem)
#endif
{
    PVoid pReqMem;
    pReqMem = dlmalloc((size_t)size);
    if (zeroMem && NULL != pReqMem) {
        // TODO: Need optimizing?
        memset(pReqMem, 0, size);
    }
    return pReqMem;
}

#if defined(MEMORYSPY) //DEBUG, OPTIMIZE
void TaskMemFree(void *pMem)
#else // RELEASE
ELAPI_(void) _CMemoryHeap_Free(PVoid pMem)
#endif
{
    dlfree(pMem);
}

#if defined(MEMORYSPY) //DEBUG, OPTIMIZE
void * TaskMemRealloc(void *pMem, UInt32 size)
#else // RELEASE
ELAPI_(PVoid) _CMemoryHeap_Realloc(PVoid pMem, MemorySize size)
#endif
{
    return dlrealloc(pMem, (size_t)size);
}

ELAPI_(Boolean) _CMemoryHeap_Trim(MemorySize pad)
{
    return dlmalloc_trim((size_t)pad);
}

ELAPI _CMemoryHeap_GetStatistics(
    MemorySize *pInUseBytes,
    MemorySize *pSystemBytes,
    MemorySize *pMaxSystemBytes)
{
    if (!pInUseBytes && !pSystemBytes && !pMaxSystemBytes) {
        return E_INVALID_ARGUMENT;
    }
    dlmalloc_stats(
        (size_t*)pInUseBytes,
        (size_t*)pSystemBytes,
        (size_t*)pMaxSystemBytes);
    return NOERROR;
}

/*
void* malloc(size_t bytes)
{
    return _CMemoryHeap_Alloc(bytes, FALSE);
}

void free(void* mem)
{
    _CMemoryHeap_Free(mem);
}
*/
/*
#if defined(MEMORYSPY) //DEBUG OPTIMIZE
UInt32 MemSpyGetMemSize(void * pv)
#else // RELEASE
UInt32 GetMemSize(void * pv)
#endif
{
    UInt32 size = 0;

    if (pv != 0) {
        mchunkptr p  = mem2chunk(pv);
#if FOOTERS
        mstate fm = get_mstate_for(p);
        if (!ok_magic(fm)) {
            USAGE_ERROR_ACTION(fm, p);
            return size;
        }
#else
#define fm gm
#endif
        if (!PREACTION(fm)) {
            size = chunksize(p);
            POSTACTION(fm);
        }
    }

    return size;
#if !FOOTERS
#undef fm
#endif
}
*/

#endif
